package com.plian.system.service.qg.subsidiary.impl;

import com.alibaba.excel.EasyExcel;
import com.alibaba.excel.ExcelWriter;
import com.alibaba.excel.write.metadata.WriteSheet;
import com.alibaba.excel.write.metadata.fill.FillConfig;
import com.alibaba.excel.write.metadata.fill.FillWrapper;
import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.plian.Tools.*;
import com.plian.Tools.pagedata.PageData;
import com.plian.system.cache.UserCache;
import com.plian.system.common.status.CheckStatus;
import com.plian.system.common.status.MyCustomCode;
import com.plian.system.constant.baseinfo.ValueSetConstant;
import com.plian.system.constant.sys.FormStatusConstant;
import com.plian.system.constant.sys.FormTypeConstant;
import com.plian.system.constant.yth.YthConstant;
import com.plian.system.dao.bt.baseinfo.BaseInfoDao;
import com.plian.system.dto.qg.subsidiary.SubsidiaryMixedReformDTO;
import com.plian.system.entity.pm.property.PropertyBasics;
import com.plian.system.entity.qg.subsidiary.MixedOwnershipStructure;
import com.plian.system.entity.qg.subsidiary.SubsidiaryIntroduceReform;
import com.plian.system.entity.qg.subsidiary.SubsidiaryMixedReform;
import com.plian.system.entity.sys.ApprovalMessage;
import com.plian.system.enumeratea.ReformStatus;
import com.plian.system.mapper.qg.subsidiary.SubsidiaryMixedReformMapper;
import com.plian.system.model.CommonCode;
import com.plian.system.model.R;
import com.plian.system.mybatis.base.BaseFlowService;
import com.plian.system.mybatis.base.BaseServiceImpl;
import com.plian.system.mybatis.search.SearchEntity;
import com.plian.system.mybatis.search.SearchParamEntiy;
import com.plian.system.mybatis.support.Condition;
import com.plian.system.service.bt.baseinfo.BaseInfoService;
import com.plian.system.service.pm.property.IPropertyBasicsService;
import com.plian.system.service.pm.property.PorpertyBasicsService;
import com.plian.system.service.qg.subsidiary.IMixedOwnershipStructureService;
import com.plian.system.service.qg.subsidiary.ISubsidiaryIntroduceReformService;
import com.plian.system.service.qg.subsidiary.ISubsidiaryMixedReformService;
import com.plian.system.service.sys.code.IFormCodeService;
import com.plian.system.service.sys.file.FileService;
import com.plian.system.service.sys.message.IApprovalMessageService;
import com.plian.system.service.sys.orgzation.IOrgService;
import com.plian.system.service.sys.user.ISysUserService;
import com.plian.system.service.wf.FormWorkflowService;
import com.plian.system.vo.qg.subsidiary.MixedOwnershipStructureVO;
import com.plian.system.vo.qg.subsidiary.SubsidiaryHistoryVO;
import com.plian.system.vo.qg.subsidiary.SubsidiaryIntroduceReformVO;
import com.plian.system.vo.qg.subsidiary.SubsidiaryMixedReformVO;
import com.plian.system.vo.report.HeaderVO;
import com.plian.system.vo.report.ReportReturnVO;
import com.plian.system.vo.report.ReportVO;
import com.plian.system.vo.yth.YthResult;
import com.plian.system.wrapper.qg.subsidiary.MixedOwnershipStructureWrapper;
import com.plian.system.wrapper.qg.subsidiary.SubsidiaryIntroduceReformWrapper;
import com.plian.system.wrapper.qg.subsidiary.SubsidiaryMixedReformWrapper;
import lombok.AllArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.exception.ExceptionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import javax.servlet.http.HttpServletResponse;
import java.io.File;
import java.io.InputStream;
import java.io.OutputStream;
import java.math.BigDecimal;
import java.net.URLEncoder;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;

import static com.plian.system.constant.sys.ApprovalMessageTypeConstant.KT_TYPE;
import static com.plian.system.constant.sys.ApprovalMessageTypeConstant.REFORM;
import static com.plian.system.constant.sys.FormStatusConstant.UNREVIEWED;

/**
 * 子企业混合所有制改革进展 服务实现类
 *
 * @author jianglei
 * @since 2019-11-05
 */
@Slf4j
@Service
@AllArgsConstructor
public class SubsidiaryMixedReformServiceImpl extends BaseServiceImpl<SubsidiaryMixedReformMapper, SubsidiaryMixedReform> implements ISubsidiaryMixedReformService, BaseFlowService {

    private SubsidiaryMixedReformMapper subsidiaryMixedReformMapper;
    private final FormWorkflowService formWorkflowService;
    private IFormCodeService formCodeService;
    private BaseInfoService baseInfoService;
    private BaseInfoDao baseInfoDao;
    private IMixedOwnershipStructureService mixedOwnershipStructureService;
    private IPropertyBasicsService propertyBasicsService;
    private ISubsidiaryIntroduceReformService subsidiaryIntroduceReformService;
    private MixedOwnershipStructureWrapper mixedOwnershipStructureWrapper;
    private SubsidiaryMixedReformWrapper subsidiaryMixedReformWrapper;
    private SubsidiaryIntroduceReformWrapper subsidiaryIntroduceReformWrapper;
    private FileService fileService;
    private IApprovalMessageService approvalMessageService;
    private IOrgService orgService;
    private ISysUserService userService;
    private PorpertyBasicsService porpertyBasicsService;

    @Override
    public boolean deleteLogic(List<Long> ids) {
        for (Long id : ids) {
            SubsidiaryMixedReform subsidiaryMixedReform = getById(id);
            if (subsidiaryMixedReform == null) {
                return false;
            } else if (subsidiaryMixedReform.getStatus() != null &&
                    (subsidiaryMixedReform.getStatus() != FormStatusConstant.STASH && subsidiaryMixedReform.getStatus() != FormStatusConstant.UNREVIEWED)) {
                return false;
            }
            formWorkflowService.deleteProcessInstance(String.valueOf(id));
        }
        mixedOwnershipStructureService.deleteLogicByMixedReformId(ids);
        return super.deleteLogic(ids);
    }

    @Override
    public Boolean finish(String id) {
        /**
         * 设置审批人和审批时间
         */
        SubsidiaryMixedReform subsidiaryMixedReform = getById(id);
        subsidiaryMixedReform.setApprovedUser(TokenUtil.getTokenUserId());
        subsidiaryMixedReform.setReformStatus(ReformStatus.ADJUSTABLE.getStatus());
        subsidiaryMixedReform.setInitialId(subsidiaryMixedReform.getId());
        Date now = DateUtil.now();
        subsidiaryMixedReform.setApprovedTime(now);
        updateById(subsidiaryMixedReform);

        return handleStatus(Long.valueOf(id), FormStatusConstant.FINISH, "审批通过");
    }

    @Override
    public Boolean reject(String id, int formState, String comment) {
        return handleStatus(Long.valueOf(id), formState, comment);
    }

    @Override
    public boolean saveOrUpdate(SubsidiaryMixedReform subsidiaryMixedReform) {
        boolean flag = false;
        if (subsidiaryMixedReform.getId() == null) {
            flag = true;
            subsidiaryMixedReform.setCode(formCodeService.getCode(FormTypeConstant.QG_SUBSIDIARY_FORM));
            subsidiaryMixedReform.setFormType(String.valueOf(FormTypeConstant.QG_SUBSIDIARY_FORM));
            subsidiaryMixedReform.setVersion(1);
            subsidiaryMixedReform.setIsLatest(2);
        }
        if (!Optional.ofNullable(subsidiaryMixedReform.getStatus()).isPresent()) {
            subsidiaryMixedReform.setStatus(FormStatusConstant.UNREVIEWED);
        }

        if (CollectionUtil.isNotEmpty(subsidiaryMixedReform.getMajorIndustryIds())) {
            subsidiaryMixedReform.setMajorIndustryId(String.join(StringPool.COMMA, subsidiaryMixedReform.getMajorIndustryIds()));
        }
        if (CollectionUtil.isNotEmpty(subsidiaryMixedReform.getMixedModeIds())) {
            subsidiaryMixedReform.setMixedModeId(String.join(StringPool.COMMA, subsidiaryMixedReform.getMixedModeIds()));
        }
        boolean result = super.saveOrUpdate(subsidiaryMixedReform);
        if (flag) {
            fileService.saveAll(String.valueOf(subsidiaryMixedReform.getId()), subsidiaryMixedReform.getDocList());
        } else {
            fileService.edit(String.valueOf(subsidiaryMixedReform.getId()), subsidiaryMixedReform.getDocList());
        }

        return result;
    }

    @Override
    public java.io.File exportExcel(JSONObject jsonObject) {
        List<SearchEntity> entityList = Optional.ofNullable(jsonObject.getJSONArray("query"))
                .map(x -> x.toJavaList(SearchEntity.class)).orElse(new ArrayList<>());
        QueryWrapper<SubsidiaryMixedReform> qw = SearchParamEntiy.getQueryWrapper(
                Condition.getQueryWrapper(new SubsidiaryMixedReform()), entityList
        );
        List<SubsidiaryMixedReform> floors = list(qw);
        // @TODO 导出EXCEL
//        return ExcelUtils.exportExcelByList(jsonObject, SubsidiaryMixedReformWrapper.build().listVO(floors));
        return null;
    }

    @Override
    public HashMap<String, Object> commit(String id) {
        handleStatus(Long.valueOf(id), FormStatusConstant.FLOW, null);

        //将需要提交的流程变量返回，用于工作流侧
        return new HashMap<String, Object>();
    }

    @Override
    public void goBackToStash(String formId) {
        handleStatus(Long.valueOf(formId), UNREVIEWED, null);
    }

    @Override
    public Boolean checkIsExisted(Long id, String code) {

        if (StringUtil.isNotBlank(code)) {
            SubsidiaryMixedReform subsidiaryMixedReform = new SubsidiaryMixedReform();
            subsidiaryMixedReform.setCode(code);
            if (Optional.ofNullable(getOne(Condition.getQueryWrapper(subsidiaryMixedReform))).isPresent()) {
                if (id == null || !id.equals(getOne(Condition.getQueryWrapper(subsidiaryMixedReform)).getId())) {
                    return false;
                }
            }
        }

        return true;
    }

    @Override
    public R checkSubmit(SubsidiaryMixedReform subsidiaryMixedReform) {

        if (!checkIsExisted(subsidiaryMixedReform.getId(), subsidiaryMixedReform.getCode())) {
            return new R(MyCustomCode.BILL_ALREADY_EXISTS2);
        }

        SubsidiaryMixedReform mixedReform = getOne(Wrappers.<SubsidiaryMixedReform>query().lambda()
                .eq(SubsidiaryMixedReform::getFormType, FormTypeConstant.QG_SUBSIDIARY_FORM)
                .eq(SubsidiaryMixedReform::getMixedEnterpriseId, subsidiaryMixedReform.getMixedEnterpriseId()));
        if (mixedReform == null) {
            return null;
        }
        if (!mixedReform.getId().equals(subsidiaryMixedReform.getId())) {
            return R.fail("该企业已混改登记");
        }
        return null;
    }

    @Override
    public ReportReturnVO mixedStatistics(SubsidiaryMixedReformDTO subsidiaryMixedReformDTO) {
        List<SubsidiaryMixedReformVO> subsidiaryMixedReformVOS = subsidiaryMixedReformMapper.mixedStatisticsList(subsidiaryMixedReformDTO);
        List<SubsidiaryMixedReformVO> data = new ArrayList<>();

        if (!CollectionUtils.isEmpty(subsidiaryMixedReformVOS)) {

            Map<String, String> allMap = baseInfoService.getChildMap(ValueSetConstant.ROOT);

            Map<String, List<SubsidiaryMixedReformVO>> map = subsidiaryMixedReformVOS.stream()
                    .filter(subsidiaryMixedReformVO -> Optional.ofNullable(subsidiaryMixedReformVO.getCreateCompanyName()).isPresent())
                    .collect(Collectors.groupingBy(SubsidiaryMixedReformVO::getCreateCompanyName));
            List<SubsidiaryMixedReformVO> sumList = new ArrayList<>();
            map.forEach((key, value) ->
            {
                data.addAll(value);
                SubsidiaryMixedReformVO sum = new SubsidiaryMixedReformVO();
                sum.setCompanyName("小计：" + value.size());
                for (SubsidiaryMixedReformVO vo : value) {
                    List<MixedOwnershipStructure> mixedOwnershipStructures = vo.getMixedOwnershipStructures();
                    if (CollectionUtil.isNotEmpty(mixedOwnershipStructures)) {
                        String str = "";
                        for (MixedOwnershipStructure mixedOwnershipStructure : mixedOwnershipStructures) {
                            if (StringUtil.isNotBlank(str)) {
                                str += " ，";
                            }
                            str += mixedOwnershipStructure.getShareholders() + ":" + mixedOwnershipStructure.getEquityRatio() + "%";
                        }
                        vo.setMixedOwnershipStructure(str);
                    }


                    if (StringUtil.isNotBlank(vo.getUnitRankId()) && allMap.containsKey(vo.getUnitRankId())) {
                        vo.setUnitRankName(allMap.get(vo.getUnitRankId()));
                    }

                    if (StringUtil.isNotBlank(vo.getMajorIndustryId())) {
                        String[] majorIndustryIds = vo.getMajorIndustryId().split(",");
                        List<String> majorIndustryNames = new ArrayList<>();
                        for (String str : majorIndustryIds) {
                            if (allMap.containsKey(str)) {
                                majorIndustryNames.add(allMap.get(str));
                            }
                        }
                        vo.setMajorIndustryNames(majorIndustryNames);

                    }

                    if (StringUtil.isNotBlank(vo.getFunctionalCategoryId()) && allMap.containsKey(vo.getFunctionalCategoryId())) {
                        vo.setFunctionalCategoryName(allMap.get(vo.getFunctionalCategoryId()));
                    }

                    if (StringUtil.isNotBlank(vo.getMixedModeId()) && allMap.containsKey(vo.getMixedModeId())) {
                        vo.setMixedModeName(allMap.get(vo.getMixedModeId()));
                    }

                    if (StringUtil.isNotBlank(vo.getMixedCategoryId()) && allMap.containsKey(vo.getMixedCategoryId())) {
                        vo.setMixedCategoryName(allMap.get(vo.getMixedCategoryId()));
                    }
                    sum.setRegisteredCapital(BigDecimalUtil.add(sum.getRegisteredCapital(), vo.getRegisteredCapital()));
                    sum.setNonpublicCapitalAmount(BigDecimalUtil.add(sum.getNonpublicCapitalAmount(), vo.getNonpublicCapitalAmount()));
                }
                sumList.add(sum);
                data.add(sum);
            });

            SubsidiaryMixedReformVO end = new SubsidiaryMixedReformVO();
            end.setCompanyName("总计：" + subsidiaryMixedReformVOS.size());
            for (SubsidiaryMixedReformVO sum : sumList) {
                end.setRegisteredCapital(BigDecimalUtil.add(end.getRegisteredCapital(), sum.getRegisteredCapital()));
                end.setNonpublicCapitalAmount(BigDecimalUtil.add(end.getNonpublicCapitalAmount(), sum.getNonpublicCapitalAmount()));
            }
            data.add(end);
        }


        ReportReturnVO reportReturnVO = new ReportReturnVO();
        ReportVO reportVO = new ReportVO();

        reportVO
                .addHeader(HeaderVO.builder().key("companyName").title("填报单位").build())
                .addHeader(HeaderVO.builder().key("mixedEnterpriseName").title("实施混改所有制改革的企业名称").build())
                .addHeader(HeaderVO.builder().key("unitRankName").title("企业级次").build())
                .addHeader(HeaderVO.builder().key("majorIndustryNames").title("所属行业").build())
                .addHeader(HeaderVO.builder().key("functionalCategoryName").title("功能分类").build())
                .addHeader(HeaderVO.builder().key("implementationTime").title("实施时间").build())
                .addHeader(HeaderVO.builder().key("mixedModeName").title("混改方式").build())
                .addHeader(HeaderVO.builder().key("mixedCategoryName").title("混改后企业类别").build())
                .addHeader(HeaderVO.builder().key("mixedRegisteredCapital").title("混改后企业注册资本（万元）").build())
                .addHeader(HeaderVO.builder().key("nonpublicCapitalAmount").title("引入非公资本金额（万元）").build())
                .addHeader(HeaderVO.builder().key("nonpublicCapitalRatio").title("非公资本占比").build())
                .addHeader(HeaderVO.builder().key("subsidiaryNum").title("子企业数").build())
                .addHeader(HeaderVO.builder().key("employeeStockRatio").title("员工持股比例").build())
                .addHeader(HeaderVO.builder().key("contacts").title("联系人").build())
                .addHeader(HeaderVO.builder().key("contactInformation").title("联系方式").build())
                .addHeader(HeaderVO.builder().key("mixedOwnershipStructure").title("混改后企业股权结构").build());

        reportVO.setData(data);
        reportReturnVO.setGrids(reportVO);
        return reportReturnVO;
    }

    @Override
    public ReportReturnVO enterpriseStatistics(SubsidiaryMixedReformDTO subsidiaryMixedReformDTO) {
        LambdaQueryWrapper<SubsidiaryMixedReform> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(SubsidiaryMixedReform::getStatus, 3);
        if (CollectionUtil.isNotEmpty(subsidiaryMixedReformDTO.getCompanyIds())) {
            queryWrapper.in(SubsidiaryMixedReform::getCreateCompanyId, subsidiaryMixedReformDTO.getCompanyIds());
        }
        List<SubsidiaryMixedReform> subsidiaryMixedReforms = list(queryWrapper);
        List<SubsidiaryMixedReformVO> data = new ArrayList<>();

        if (!CollectionUtils.isEmpty(subsidiaryMixedReforms)) {
            List<String> delIds = new ArrayList<>();
            for (SubsidiaryMixedReform subsidiaryMixedReform : subsidiaryMixedReforms) {

                String id = subsidiaryMixedReform.getMixedEnterpriseId();
                if (StringUtil.isNotBlank(id)) {
                    List<String> childrenIds = porpertyBasicsService.findChildrenIds(id);
                    if (CollectionUtil.isNotEmpty(childrenIds)) {
                        delIds.addAll(childrenIds);
                    }
                }
            }

            subsidiaryMixedReforms.removeIf(subsidiaryMixedReform -> delIds.contains(subsidiaryMixedReform.getMixedEnterpriseId()));

            data.addAll(subsidiaryMixedReformWrapper.entityToVO(subsidiaryMixedReforms));
            SubsidiaryMixedReformVO end = new SubsidiaryMixedReformVO();
            end.setMixedEnterpriseName("总计：" + subsidiaryMixedReforms.size());
            data.add(end);
        }


        ReportReturnVO reportReturnVO = new ReportReturnVO();
        ReportVO reportVO = new ReportVO();

        reportVO
                .addHeader(HeaderVO.builder().key("mixedEnterpriseName").title("企业名称").build())
                .addHeader(HeaderVO.builder().key("unitRankName").title("企业级次").build())
                .addHeader(HeaderVO.builder().key("majorIndustryNames").title("所属行业").build())
                .addHeader(HeaderVO.builder().key("functionalCategoryName").title("功能分类").build())
                .addHeader(HeaderVO.builder().key("subsidiaryNum").title("子企业数").build());

        reportVO.setData(data);
        reportReturnVO.setGrids(reportVO);
        return reportReturnVO;
    }

    @Override
    public ReportReturnVO privateCapitalInfoReport(SubsidiaryMixedReformDTO subsidiaryMixedReformDTO) {
        QueryWrapper<SubsidiaryMixedReform> queryWrapper = new QueryWrapper<>();
        ReportReturnVO reportReturnVO = new ReportReturnVO();
        if (Optional.ofNullable(subsidiaryMixedReformDTO.getCompanyIds()).isPresent()) {
            queryWrapper.in("create_company_id", subsidiaryMixedReformDTO.getCompanyIds());
        }
        if (StringUtil.isNoneBlank(subsidiaryMixedReformDTO.getCompanyName())) {
            QueryWrapper propertyQueryWrapper = new QueryWrapper();
            propertyQueryWrapper.like("org_name", subsidiaryMixedReformDTO.getCompanyName());
            propertyQueryWrapper.eq("status", 3);
            propertyQueryWrapper.eq("competent_organization", TokenUtil.getCompetentOrganization());
            List<PropertyBasics> propertyBasicsList = propertyBasicsService.list(propertyQueryWrapper);
            if (propertyBasicsList.size() == 0) {
                queryWrapper.eq("status", -1);
            } else {
                List<String> companyIds = propertyBasicsList.stream().map(record -> record.getId()).collect(Collectors.toList());
                queryWrapper.in("mixed_enterprise_id", companyIds);
            }
        }
        queryWrapper.eq("status", 3);

        if (StringUtil.isNoneBlank(subsidiaryMixedReformDTO.getMixedCategoryId())) {
            queryWrapper.eq("mixed_category_id", subsidiaryMixedReformDTO.getMixedCategoryId());
        }
        if (StringUtil.isNoneBlank(subsidiaryMixedReformDTO.getFunctionalCategoryId())) {
            queryWrapper.eq("functional_category_id", subsidiaryMixedReformDTO.getFunctionalCategoryId());
        }
        if (StringUtil.isNoneBlank(subsidiaryMixedReformDTO.getMixedModeId())) {
            queryWrapper.eq("mixed_mode_id", subsidiaryMixedReformDTO.getMixedModeId());
        }
        if (StringUtil.isNoneBlank(subsidiaryMixedReformDTO.getMixedType())) {
            queryWrapper.eq("mixed_type", subsidiaryMixedReformDTO.getMixedType());
        }
        if (Optional.ofNullable(subsidiaryMixedReformDTO.getStartTime()).isPresent()) {
            queryWrapper.ge("implementation_time", subsidiaryMixedReformDTO.getStartTime());
        }
        if (Optional.ofNullable(subsidiaryMixedReformDTO.getEndTime()).isPresent()) {
            queryWrapper.le("implementation_time", subsidiaryMixedReformDTO.getEndTime());
        }
        List<SubsidiaryMixedReform> subsidiaryMixedReforms = list(queryWrapper);

        List<SubsidiaryMixedReformVO> tempData = subsidiaryMixedReformWrapper.entityToVO(subsidiaryMixedReforms);

        Map<String, SubsidiaryMixedReformVO> subsidiaryMixedReformMap = tempData.stream().collect(
                Collectors.groupingBy(record -> record.getMixedEnterpriseId(), Collectors.collectingAndThen(
                        Collectors.reducing((c1, c2) -> c1.getUpdateTime().compareTo(c2.getUpdateTime()) >= 0 ? c1 : c2), Optional::get)
                ));
        List<SubsidiaryMixedReformVO> data = new ArrayList<>(subsidiaryMixedReformMap.values());

        //混改后企业股权结构
        List<MixedOwnershipStructure> mixedOwnershipStructureList = mixedOwnershipStructureService.list(
                new LambdaQueryWrapper<MixedOwnershipStructure>().in(MixedOwnershipStructure::getMixedReformId, data.stream().map(SubsidiaryMixedReformVO::getId).collect(Collectors.toList())));
        //根据主表Id
        if (CollectionUtil.isNotEmpty(mixedOwnershipStructureList)) {
            //code
            try {
                List<PageData> pageData = baseInfoDao.findbyParentid(ValueSetConstant.HOLD_NATURE);
                Map<Long, List<MixedOwnershipStructure>> mapByMixed = mixedOwnershipStructureList.stream().collect(Collectors.groupingBy(MixedOwnershipStructure::getMixedReformId));
                for (SubsidiaryMixedReformVO vo : data) {
                    List<MixedOwnershipStructure> structureList = mapByMixed.get(vo.getId());
                    if (CollectionUtil.isNotEmpty(structureList)) {
                        String mixedOwnershipStructuresFullStr = "";
                        for (MixedOwnershipStructure structure : structureList) {
                            String shareholders = structure.getShareholders();
                            String shareholdersNatureName = "";
                            for (PageData pd : pageData) {
                                String code = pd.getString("code");
                                if (code.equals(structure.getShareholdersNature())) {
                                    shareholdersNatureName = pd.getString("name");
                                }
                            }
                            BigDecimal equityRatio = structure.getEquityRatio() == null ? new BigDecimal(0) : structure.getEquityRatio();
                            String orgPaidCapital = structure.getOrgPaidCapital() == null ? "/" : structure.getOrgPaidCapital();
                            String orgSubscribedCapital = structure.getOrgSubscribedCapital() == null ? "/" : structure.getOrgSubscribedCapital();
                            mixedOwnershipStructuresFullStr = mixedOwnershipStructuresFullStr + shareholders + "," + shareholdersNatureName + "," + equityRatio + "," + orgPaidCapital + "," + orgSubscribedCapital + ";";
                        }
                        vo.setMixedOwnershipStructureFullStr(mixedOwnershipStructuresFullStr);
                    }
                }
            } catch (Exception e) {
                e.printStackTrace();
            }

        }

        ReportVO reportVO = new ReportVO();

        reportVO
                .addHeader(HeaderVO.builder().key("code").title("单据编码").build())
                .addHeader(HeaderVO.builder().key("mixedEnterpriseName").title("混改企业名称").build())
                .addHeader(HeaderVO.builder().key("affiliatedOrgFullName").title("所属集团名称").build())
                .addHeader(HeaderVO.builder().key("unitRankName").title("企业级次").build())
                .addHeader(HeaderVO.builder().key("majorIndustryNames").title("所属行业").build())
                .addHeader(HeaderVO.builder().key("functionalCategoryName").title("功能分类").build())
                .addHeader(HeaderVO.builder().key("implementationTime").title("首次混改日期").build())
                .addHeader(HeaderVO.builder().key("mixedModeName").title("混改方式").build())
                .addHeader(HeaderVO.builder().key("mixedTypeName").title("混改类型").build())
                .addHeader(HeaderVO.builder().key("mixedCategoryName").title("企业类别").build())
                .addHeader(HeaderVO.builder().key("stateFundedRelationNamne").title("与国家出资企业关系").build())
                .addHeader(HeaderVO.builder().key("mixedRegisteredCapital").title("注册资本").build())
                .addHeader(HeaderVO.builder().key("subsidiaryNum").title("子企业数").build())
                .addHeader(HeaderVO.builder().key("nonpublicCapitalRatio").title("民营资本占比%").build())
                .addHeader(HeaderVO.builder().key("nonpublicCapitalAmount").title("引入民营资本金额").build())
                .addHeader(HeaderVO.builder().key("employeeStockRatio").title("员工持股比例%").build())
                .addHeader(HeaderVO.builder().key("employeeSharingholdingNums").title("员工持股人数").build())
                .addHeader(HeaderVO.builder().key("mixedOwnershipStructureFullStr").title("混改后企业股权结构").build());

        reportVO.setData(data);
        reportReturnVO.setGrids(reportVO);

        return reportReturnVO;
    }

    @Override
    public List<PageData> findByIds(List<String> formIds) {
        LambdaQueryWrapper<SubsidiaryMixedReform> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.in(SubsidiaryMixedReform::getId, Func.toLongList(org.apache.commons.lang3.StringUtils.join(formIds, StringPool.COMMA)));
        List<SubsidiaryMixedReform> subsidiaryMixedReforms = list(queryWrapper);
        List<SubsidiaryMixedReformVO> subsidiaryMixedReformVOS = subsidiaryMixedReformWrapper.entityToVO(subsidiaryMixedReforms);
        List<PageData> pageDataList = new ArrayList<>();
        try {
            if (CollectionUtil.isNotEmpty(subsidiaryMixedReformVOS)) {
                for (SubsidiaryMixedReformVO vo : subsidiaryMixedReformVOS) {
                    PageData pd = new PageData();
                    pd.put("id", vo.getId());
                    pd.put("UNITNAME", vo.getMixedEnterpriseName());
                    pd.put("APPLICANTNAME", vo.getCreateUserName());
                    pd.put("applicantId", vo.getCreateUser());
                    pd.put("applyOrganizationId", vo.getMixedEnterpriseId());
                    pd.put("formType", FormTypeConstant.QG_SUBSIDIARY_FORM);
                    pd.put("orgName", vo.getMixedEnterpriseName());
                    pageDataList.add(pd);
                }
            }

            return pageDataList;
        } catch (Exception e) {
            log.error(ExceptionUtils.getFullStackTrace(e));
        }
        return pageDataList;
    }

    @Override
    public List<Integer> getFormType() {
        return Arrays.asList(FormTypeConstant.QG_SUBSIDIARY_FORM);
    }

    @Override
    @Transactional(rollbackFor = RuntimeException.class)
    public Boolean submit(SubsidiaryMixedReform subsidiaryMixedReform) {
        boolean result = saveOrUpdate(subsidiaryMixedReform);
        if (result) {
            List<MixedOwnershipStructure> mixedOwnershipStructures = subsidiaryMixedReform.getMixedOwnershipStructures();
            if (CollectionUtil.isNotEmpty(mixedOwnershipStructures)) {
                for (MixedOwnershipStructure mixedOwnershipStructure : mixedOwnershipStructures) {
                    if (mixedOwnershipStructure.getId() != null &&
                            Optional.ofNullable(mixedOwnershipStructure.getIsDeleted()).isPresent() && mixedOwnershipStructure.getIsDeleted().intValue() == 1) {
                        mixedOwnershipStructureService.removeById(mixedOwnershipStructure.getId());
                    } else {
                        mixedOwnershipStructure.setMixedReformId(subsidiaryMixedReform.getId());
                        mixedOwnershipStructureService.saveOrUpdate(mixedOwnershipStructure);
                    }
                }
            }
        }

        return result;
    }

    @Override
    public R<SubsidiaryMixedReformVO> getDetailObj(SubsidiaryMixedReformVO subsidiaryMixedReformVO) {
        if (!Optional.ofNullable(subsidiaryMixedReformVO).isPresent()) {
            return new R(CommonCode.FAIL);
        }
        subsidiaryMixedReformVO.setMixedOwnershipStructureVOS(mixedOwnershipStructureWrapper.entityToVO(mixedOwnershipStructureService
                .list(new LambdaQueryWrapper<MixedOwnershipStructure>().eq(MixedOwnershipStructure::getMixedReformId, subsidiaryMixedReformVO.getId()))));
        R<SubsidiaryMixedReformVO> objResult = new R<>(CommonCode.SUCCESS);
        objResult.setPageData(subsidiaryMixedReformVO);
        return R.data(subsidiaryMixedReformVO);
    }

    @Override
    public SubsidiaryMixedReformVO superiorFlag(String propertyId) {
        SubsidiaryMixedReformVO subsidiaryMixedReformVO = new SubsidiaryMixedReformVO();
        subsidiaryMixedReformVO.setSuperiorFlag(1);
        try {
            PropertyBasics propertyBasics = propertyBasicsService.getById(propertyId);
            if (propertyBasics == null) {
                return subsidiaryMixedReformVO;
            }
            String parentId = propertyBasics.getParentId();
            if (StringUtil.isBlank(parentId)) {
                return subsidiaryMixedReformVO;
            }

            if (CollectionUtil.isNotEmpty(list(new LambdaQueryWrapper<SubsidiaryMixedReform>().eq(SubsidiaryMixedReform::getMixedEnterpriseId, parentId)))) {
                subsidiaryMixedReformVO.setSuperiorFlag(2);
                return subsidiaryMixedReformVO;
            }

            if (CollectionUtil.isNotEmpty(subsidiaryIntroduceReformService
                    .list(new LambdaQueryWrapper<SubsidiaryIntroduceReform>().eq(SubsidiaryIntroduceReform::getCompanyId, parentId)))) {
                subsidiaryMixedReformVO.setSuperiorFlag(2);
                return subsidiaryMixedReformVO;
            }

        } catch (Exception e) {
            log.error(ExceptionUtils.getFullStackTrace(e));
        }

        return subsidiaryMixedReformVO;
    }

    @Override
    public void exportDetailExcel(SubsidiaryMixedReformVO subsidiaryMixedReformVO, HttpServletResponse response) {
        try {
            String separator = File.separator;
            String exlPath = separator + "exceldemo" + separator + "privateCapitalInfo.xlsx";
            InputStream inputStream = this.getClass().getResourceAsStream(exlPath);
            String fileName = URLEncoder.encode("引进民营资本信息情况", "UTF-8");
            response.setHeader("Content-disposition", "attachment;filename=" + fileName + ".xlsx");
            // 设置响应头和客户端保存文件名
            response.setCharacterEncoding("utf-8");
            OutputStream outputStream = response.getOutputStream();// 取得输出流
            ExcelWriter excelWriter = EasyExcel.write(outputStream).withTemplate(inputStream).build();
            WriteSheet writeSheet = EasyExcel.writerSheet(0).build();
            FillConfig fillConfig = FillConfig.builder().forceNewRow(Boolean.TRUE).build();
            String implementationTimeStr = "";
            Date implementationTime = subsidiaryMixedReformVO.getImplementationTime();
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
            if (implementationTime != null) {
                implementationTimeStr = sdf.format(implementationTime);
                subsidiaryMixedReformVO.setImplementationTimeStr(implementationTimeStr);
            }
            excelWriter.fill(subsidiaryMixedReformVO, writeSheet);
            subsidiaryMixedReformVO.setMixedOwnershipStructureVOS(mixedOwnershipStructureWrapper.entityToVO(mixedOwnershipStructureService
                    .list(new QueryWrapper<MixedOwnershipStructure>().eq("mixed_reform_id", subsidiaryMixedReformVO.getId()))));
            String mixedOwnershipStructuresFullStr = "";

            for (int i = 0; i < subsidiaryMixedReformVO.getMixedOwnershipStructureVOS().size(); i++) {
                MixedOwnershipStructureVO record = subsidiaryMixedReformVO.getMixedOwnershipStructureVOS().get(i);
                record.setIndex(i + 1);
                String shareholders = record.getShareholders();
                String shareholdersNatureName = record.getShareholdersNatureName() == null ? "/" : record.getShareholdersNatureName();
                BigDecimal equityRatio = record.getEquityRatio() == null ? new BigDecimal(0) : record.getEquityRatio();
                String orgPaidCapital = record.getOrgPaidCapital() == null ? "/" : record.getOrgPaidCapital();
                String orgSubscribedCapital = record.getOrgSubscribedCapital() == null ? "/" : record.getOrgSubscribedCapital();
                mixedOwnershipStructuresFullStr += shareholders + "," + shareholdersNatureName + "," + equityRatio + "," + orgPaidCapital + "," + orgSubscribedCapital + ";";
            }
            ;
            subsidiaryMixedReformVO.setMixedOwnershipStructureFullStr(mixedOwnershipStructuresFullStr);
            subsidiaryMixedReformVO.setStatusName("审批通过");

            excelWriter.fill(new FillWrapper("t", subsidiaryMixedReformVO.getMixedOwnershipStructureVOS()), fillConfig, writeSheet);
            excelWriter.finish();
            inputStream.close();
            outputStream.close();
        } catch (Exception e) {
            log.error(ExceptionUtils.getStackTrace(e));
        }
    }

    @Override
    public List<SubsidiaryHistoryVO> historyList(String companyId) {
        List<SubsidiaryHistoryVO> resultList = new ArrayList<>();
        QueryWrapper mixQueryWrapper = new QueryWrapper();
        mixQueryWrapper.eq("mixed_enterprise_id", companyId);
        List<SubsidiaryMixedReformVO> subsidiaryMixedReformList = subsidiaryMixedReformWrapper.entityToVO(list(mixQueryWrapper));
        subsidiaryMixedReformList.forEach(record -> {
            Long id = record.getId();
            SubsidiaryHistoryVO subsidiaryHistoryVO = new SubsidiaryHistoryVO();
            subsidiaryHistoryVO.setId(id.toString());
            subsidiaryHistoryVO.setType("1");
            subsidiaryHistoryVO.setFormType("13");
            subsidiaryHistoryVO.setTypeName("引进民营资本");
            subsidiaryHistoryVO.setCompanyName(record.getMixedEnterpriseName());
            subsidiaryHistoryVO.setImplementationTime(record.getImplementationTime());
            resultList.add(subsidiaryHistoryVO);
        });
        QueryWrapper introduceQueryWrapper = new QueryWrapper();
        introduceQueryWrapper.eq("company_id", companyId);
        List<SubsidiaryIntroduceReform> tempList = subsidiaryIntroduceReformService.list(introduceQueryWrapper);
        List<SubsidiaryIntroduceReformVO> introduceReformList = subsidiaryIntroduceReformWrapper.entityToVO(tempList);
        introduceReformList.forEach(record -> {
            Long id = record.getId();
            SubsidiaryHistoryVO subsidiaryHistoryVO = new SubsidiaryHistoryVO();
            subsidiaryHistoryVO.setId(id.toString());
            subsidiaryHistoryVO.setType("2");
            subsidiaryHistoryVO.setFormType("123");
            subsidiaryHistoryVO.setTypeName("引进非市级国有资本");
            subsidiaryHistoryVO.setCompanyName(record.getCompanyName());
            subsidiaryHistoryVO.setImplementationTime(record.getImplementationTime());
            resultList.add(subsidiaryHistoryVO);
        });
        return resultList;
    }

    /**
     * 统一处理状态机事件方法
     *
     * @param id           主键
     * @param updateStatus 更新状态
     * @return boolean
     */
    private Boolean handleStatus(Long id, int updateStatus, String comment) {
        try {
            SubsidiaryMixedReform subsidiaryMixedReform = getById(id);
            subsidiaryMixedReform.setStatus(updateStatus);
            if (StringUtil.isNotBlank(subsidiaryMixedReform.getDataSource()) &&
                    StringUtil.isNotBlank(subsidiaryMixedReform.getDataSourceId())) {
                if (updateStatus == FormStatusConstant.FINISH || updateStatus == FormStatusConstant.REJECT) {
                    ApprovalMessage approvalMessage = new ApprovalMessage();
                    approvalMessage.setDataSourceId(subsidiaryMixedReform.getDataSourceId());
                    approvalMessage.setType(REFORM);
                    approvalMessage.setOpinion(comment);
                    approvalMessage.setIsApprove(updateStatus == FormStatusConstant.FINISH ? 2 : 1);
                    approvalMessage.setIsSend(1);
                    approvalMessage.setDataSourceType(KT_TYPE);
                    if (subsidiaryMixedReform.getDataSource().equals(YthConstant.DATA_NINGBO)) {
                        approvalMessage.setDataSourceType(YthConstant.DATA_NINGBO);
                        approvalMessage.setFilingUserName(UserCache.userIdToName(TokenUtil.getTokenUserId()));
                        approvalMessage.setFormType(FormTypeConstant.QG_SUBSIDIARY_FORM);
                        approvalMessage.setFilingCode(subsidiaryMixedReform.getCode());
                    }
                    approvalMessageService.save(approvalMessage);
                }
            }
            updateById(subsidiaryMixedReform);
            return true;
        } catch (Exception e) {
            log.error(ExceptionUtils.getFullStackTrace(e));
            return false;
        }
    }

    @Override
    @Transactional(rollbackFor = RuntimeException.class)
    public String saveMixedreforms(String data) {
        YthResult ythResult = new YthResult();
        //成功的id集合
        List<String> successIds = new ArrayList<>();
        //失败的id集合
        List<String> failIds = new ArrayList<>();
        //失败的原因
        List<String> failReasons = new ArrayList<>();
        //将json字符串转换成list
        List<SubsidiaryMixedReform> dataList = JSON.parseArray(data, SubsidiaryMixedReform.class);
        if (CollectionUtil.isNotEmpty(dataList)) {
            Map<String, String> orgSourceMap = orgService.getSourceId();
            Map<String, String> userSourceMap = userService.getSourceId();
            //已经有的混改，不能再混改
            List<SubsidiaryMixedReform> subsidiaryMixedReforms = list(Wrappers.<SubsidiaryMixedReform>query().lambda()
                    .eq(SubsidiaryMixedReform::getFormType, FormTypeConstant.QG_SUBSIDIARY_FORM));
            Set<String> mixOrgIds = subsidiaryMixedReforms.stream().map(SubsidiaryMixedReform::getMixedEnterpriseId).collect(Collectors.toSet());

            //根据datasourceIds 查询出所有的数据
            List<SubsidiaryMixedReform> list = list(new LambdaQueryWrapper<SubsidiaryMixedReform>().in(SubsidiaryMixedReform::getDataSourceId, dataList.stream().map(SubsidiaryMixedReform::getDataSourceId).toArray()));
            if (CollectionUtil.isNotEmpty(list)) {
                //删除子集
                List<Long> ids = list.stream().map(SubsidiaryMixedReform::getId).collect(Collectors.toList());
                mixedOwnershipStructureService.remove(new LambdaQueryWrapper<MixedOwnershipStructure>().in(MixedOwnershipStructure::getMixedReformId, ids));
            }
            //如果数据库中有数据，就更新，没有就新增
            for (SubsidiaryMixedReform entity : dataList) {
                transfer(entity, orgSourceMap, userSourceMap);
                if (mixOrgIds.contains(entity.getMixedEnterpriseId())) {
                    failIds.add(entity.getDataSourceId());
                    failReasons.add("该企业已经混改，不能再混改");
                    continue;
                }
                //id重复略过
                if (CollectionUtil.isNotEmpty(list)) {
                    List<String> olIds = list.stream().map(SubsidiaryMixedReform::getDataSourceId).collect(Collectors.toList());
                    String dataSourceId = entity.getDataSourceId();
                    //判断数据库中是否有数据
                    if (olIds.contains(dataSourceId)) {
                        for (SubsidiaryMixedReform oldEntity : list) {
                            if (dataSourceId.equals(oldEntity.getDataSourceId())) {
                                //判断status是否为0，如果是0，就更新，不是0，就不更新
                                if (CheckStatus.checkCode(oldEntity.getStatus())) {
                                    successIds.add(dataSourceId);
                                    entity.setId(oldEntity.getId());
                                    entity.setDataSource(YthConstant.DATA_NINGBO);
                                    submit(entity);
                                    list.remove(oldEntity);
                                    break;
                                } else {
                                    failIds.add(dataSourceId);
                                    failReasons.add("dataSourceId:" + dataSourceId + "数据已提交且已经在流程中，无法更新");
                                    break;
                                }
                            }
                        }
                    } else {
                        //如果数据库中没有数据，就新增
                        entity.setDataSource(YthConstant.DATA_NINGBO);
                        submit(entity);
                        successIds.add(entity.getDataSourceId());
                    }
                } else {
                    //如果数据库中没有数据，就新增
                    entity.setDataSource(YthConstant.DATA_NINGBO);
                    submit(entity);
                    successIds.add(entity.getDataSourceId());
                }
            }
        } else {
            failReasons.add("数据为空");
        }
        ythResult.setSuccessIds(successIds);
        ythResult.setFailIds(failIds);
        ythResult.setFailReason(StringUtils.join(failReasons, ";"));
        //ythResult转换成json字符串
        return JSON.toJSONString(ythResult);
    }

    private void transfer(SubsidiaryMixedReform entity, Map<String, String> orgSourceMap,
                          Map<String, String> userSourceMap) {
        Optional.ofNullable(entity.getCreateCompanyId()).ifPresent(m ->
                {
                    String orgId = orgSourceMap.get(m);
                    if (StringUtil.isNotBlank(orgId)) {
                        entity.setCreateCompanyId(orgId);
                    }
                }
        );
        Optional.ofNullable(entity.getCreateUser()).ifPresent(m ->
                {
                    String userId = userSourceMap.get(m);
                    if (StringUtil.isNotBlank(userId)) {
                        entity.setCreateUser(userId);
                    }
                }
        );
    }

}
